package com.example.composemodifiterdemo

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.*
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt


/**
 * @auth: njb
 * @date: 2023/1/17 10:51
 * @desc:
 */
class CustomWeightActivity : ComponentActivity() {
    val topics = listOf(
        "Arts & Crafts", "Beauty", "Books", "Business", "Comics", "Culinary",
        "Design", "Fashion", "Film", "History", "Maths", "Music", "People", "Philosophy",
        "Religion", "Social sciences", "Technology", "TV", "Writing"
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CallingComposable()
            Chip(text = "Colleague" + "Hey, take a look at Jetpack Compose, it's great!")
            BodyContent()
        }
    }

    fun Modifier.firstBaselineToTop(
        firstBaselineToTop: Dp
    ) = layout { measurable, constraints ->
        // Measure the composable
        val placeable = measurable.measure(constraints)

        // Check the composable has a first baseline
        check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
        val firstBaseline = placeable[FirstBaseline]

        // Height of the composable with padding - first baseline
        val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
        val height = placeable.height + placeableY
        layout(placeable.width, height) {
            // Where the composable gets placed
            placeable.placeRelative(0, placeableY)
        }
    }

    @Preview
    @Composable
    fun TextWithPaddingToBaselinePreview() {
        MaterialTheme {
            Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
        }
    }

    @Preview
    @Composable
    fun CallingComposable(modifier: Modifier = Modifier) {
        MyBasicColumn(modifier.padding(8.dp)) {
            Text("MyBasicColumn")
            Text("places items")
            Text("vertically.")
            Text("We've done it by hand!")
        }
    }

    @Composable
    fun MyBasicColumn(
        modifier: Modifier = Modifier,
        content: @Composable () -> Unit
    ) {
        Layout(
            modifier = modifier,
            content = content
        ) { measurables, constraints ->
            // Don't constrain child views further, measure them with given constraints
            // List of measured children
            val placeables = measurables.map { measurable ->
                // Measure each children
                measurable.measure(constraints)
            }

            // Set the size of the layout as big as it can
            layout(constraints.maxWidth, constraints.maxHeight) {
                // Track the y co-ord we have placed children up to
                var yPosition = 0

                // Place children in the parent layout
                placeables.forEach { placeable ->
                    // Position item on the screen
                    placeable.placeRelative(x = 0, y = yPosition)

                    // Record the y co-ord placed up to
                    yPosition += placeable.height
                }
            }
        }
    }

    @Composable
    fun Chip(modifier: Modifier = Modifier, text: String) {
        Card(
            modifier = modifier,
            border = BorderStroke(color = Color.Black, width = Dp.Hairline),
            shape = RoundedCornerShape(8.dp)
        ) {
            Row(
                modifier = Modifier.padding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 4.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Box(
                    modifier = Modifier
                        .size(30.dp, 30.dp)
                        .background(color = MaterialTheme.colorScheme.secondary)
                )
                // 创建4dp的空隙
                Spacer(Modifier.width(4.dp))
                Text(text = text)
            }
        }
    }

    @Composable
    fun StaggeredGrid(
        modifier: Modifier = Modifier,
        // 默认显示的行数
        rows: Int = 3,
        content: @Composable () -> Unit
    ) {
        Layout(
            modifier = modifier,
            content = content
        ) { measurables, constraints ->

            // 每行的宽度
            val rowWidths = IntArray(rows) {0}
            // 每行的高度
            val rowHeights = IntArray(rows) {0}

            val placeables = measurables.mapIndexed { index, measurable ->
                // measure每一个孩子
                val placeable = measurable.measure(constraints)

                val row = index % rows
                // 根据children累计每行的宽度
                rowWidths[row] += placeable.width
                // 选择children中最高的高度
                rowHeights[row] = max(rowHeights[row], placeable.height)

                placeable
            }

            // 选择所有行中最宽的宽度
            val width = rowWidths.maxOrNull()
            // 限制rowWidths在minWidth和maxWidth之间                           ?.coerceIn(constraints.minWidth.rangeTo(constraints.maxWidth))
            // 如果rowWidths为null，则设置为minWidth
                ?: constraints.minWidth
            // 累加所有行的高度
            val height = rowHeights.sumOf { it}
                // 限制rowHeights在minHeight和maxHeight之间
                .coerceIn(constraints.minHeight.rangeTo(constraints.maxHeight))

            // 计算每行纵向显示的位置
            val rowY = IntArray(rows) { 0 }
            for (i in 1 until rows) {
                rowY[i] = rowY[i-1] + rowHeights[i-1]
            }

            // width,height为父布局的宽度和高度（即StaggeredGrids）
            layout(width, height) {
                val rowX = IntArray(rows) { 0 }
                placeables.forEachIndexed { index, placeable ->
                    val row = index % rows
                    placeable.placeRelative(
                        x = rowX[row],
                        y = rowY[row]
                    )
                    rowX[row] += placeable.width
                }
            }
        }
    }

    @Preview
    @Composable
    fun BodyContent() {
        // 不设置horizontalScroll的话，横向无法滑动
        StaggeredGrid(modifier = Modifier.horizontalScroll(rememberScrollState()), rows = 5) {
            for (topic in topics) {
                Chip(modifier = Modifier.padding(8.dp), text = topic)
            }
        }
    }

}